import React, { useRef, useEffect } from 'react';
import './style.less';

interface TechNode {
  id: string;
  name: string;
  category: string;
  size: number;
  color: string;
  x?: number;
  y?: number;
  vx?: number;
  vy?: number;
}

interface TechLink {
  source: string;
  target: string;
  strength: number;
}

interface TechCanvasProps {
  width?: number;
  height?: number;
  nodes: TechNode[];
  links: TechLink[];
}

const TechCanvas: React.FC<TechCanvasProps> = ({
  width = 800,
  height = 600,
  nodes,
  links
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const animationRef = useRef<number>();
  
  // 初始化节点位置
  const initializeNodes = () => {
    return nodes.map(node => ({
      ...node,
      x: Math.random() * width,
      y: Math.random() * height,
      vx: 0,
      vy: 0
    }));
  };

  // 力导向图算法
  const simulateForces = (simulationNodes: TechNode[], simulationLinks: TechLink[]) => {
    // 重力常数
    const GRAVITY = 0.1;
    // 排斥力常数
    const REPULSION = 800;
    // 弹簧长度
    const SPRING_LENGTH = 100;
    // 弹簧刚度
    const SPRING_COEFFICIENT = 0.01;
    // 阻尼系数
    const DAMPING = 0.9;

    // 计算节点间的排斥力
    for (let i = 0; i < simulationNodes.length; i++) {
      const nodeA = simulationNodes[i];
      
      // 向中心的引力
      const dx = width / 2 - nodeA.x!;
      const dy = height / 2 - nodeA.y!;
      const distance = Math.sqrt(dx * dx + dy * dy);
      
      nodeA.vx! += (dx / distance) * GRAVITY;
      nodeA.vy! += (dy / distance) * GRAVITY;

      // 节点间的排斥力
      for (let j = i + 1; j < simulationNodes.length; j++) {
        const nodeB = simulationNodes[j];
        
        const dx = nodeB.x! - nodeA.x!;
        const dy = nodeB.y! - nodeA.y!;
        const distance = Math.sqrt(dx * dx + dy * dy) || 1;
        
        const force = REPULSION / (distance * distance);
        
        const forceX = (dx / distance) * force;
        const forceY = (dy / distance) * force;
        
        nodeA.vx! -= forceX;
        nodeA.vy! -= forceY;
        nodeB.vx! += forceX;
        nodeB.vy! += forceY;
      }
    }

    // 计算连接的弹簧力
    for (const link of simulationLinks) {
      const sourceNode = simulationNodes.find(node => node.id === link.source);
      const targetNode = simulationNodes.find(node => node.id === link.target);
      
      if (sourceNode && targetNode) {
        const dx = targetNode.x! - sourceNode.x!;
        const dy = targetNode.y! - sourceNode.y!;
        const distance = Math.sqrt(dx * dx + dy * dy) || 1;
        
        const displacement = distance - SPRING_LENGTH;
        const springForce = displacement * SPRING_COEFFICIENT * link.strength;
        
        const forceX = (dx / distance) * springForce;
        const forceY = (dy / distance) * springForce;
        
        sourceNode.vx! += forceX;
        sourceNode.vy! += forceY;
        targetNode.vx! -= forceX;
        targetNode.vy! -= forceY;
      }
    }

    // 更新位置并应用阻尼
    for (const node of simulationNodes) {
      node.vx! *= DAMPING;
      node.vy! *= DAMPING;
      
      node.x! += node.vx!;
      node.y! += node.vy!;
      
      // 边界检查
      if (node.x! < node.size) node.x = node.size;
      if (node.x! > width - node.size) node.x = width - node.size;
      if (node.y! < node.size) node.y = node.size;
      if (node.y! > height - node.size) node.y = height - node.size;
    }

    return simulationNodes;
  };

  // 绘制函数
  const draw = (ctx: CanvasRenderingContext2D, simulationNodes: TechNode[], simulationLinks: TechLink[]) => {
    ctx.clearRect(0, 0, width, height);
    
    // 绘制连接线
    ctx.lineWidth = 1;
    ctx.strokeStyle = 'rgba(200, 200, 200, 0.6)';
    
    for (const link of simulationLinks) {
      const sourceNode = simulationNodes.find(node => node.id === link.source);
      const targetNode = simulationNodes.find(node => node.id === link.target);
      
      if (sourceNode && targetNode) {
        ctx.beginPath();
        ctx.moveTo(sourceNode.x!, sourceNode.y!);
        ctx.lineTo(targetNode.x!, targetNode.y!);
        ctx.stroke();
      }
    }
    
    // 绘制节点
    for (const node of simulationNodes) {
      ctx.beginPath();
      ctx.fillStyle = node.color;
      ctx.arc(node.x!, node.y!, node.size, 0, Math.PI * 2);
      ctx.fill();
      
      // 绘制节点文本
      ctx.fillStyle = '#333';
      ctx.font = '12px Arial';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(node.name, node.x!, node.y!);
    }
  };

  useEffect(() => {
    if (!canvasRef.current) return;
    
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    
    if (!ctx) return;
    
    // 设置canvas尺寸
    canvas.width = width;
    canvas.height = height;
    
    // 初始化节点位置
    let simulationNodes = initializeNodes();
    
    // 动画循环
    const animate = () => {
      // 模拟力导向
      simulationNodes = simulateForces(simulationNodes, links);
      
      // 绘制
      draw(ctx, simulationNodes, links);
      
      // 继续动画
      animationRef.current = requestAnimationFrame(animate);
    };
    
    // 开始动画
    animate();
    
    // 清理
    return () => {
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, [width, height, nodes, links]);

  return (
    <div className="tech-canvas-container">
      <canvas ref={canvasRef} className="tech-canvas" />
    </div>
  );
};

export default TechCanvas;